package org.i9.slb.platform.anseko.console.service.impl;

import org.i9.slb.platform.anseko.common.SimulatorUtils;
import org.i9.slb.platform.anseko.console.remote.CoreserviceRemoteService;
import org.i9.slb.platform.anseko.console.service.SimulatorService;
import org.i9.slb.platform.anseko.console.utils.CommandExecuteRemoteService;
import org.i9.slb.platform.anseko.console.utils.SimulatorBuilderFactory;
import org.i9.slb.platform.anseko.downstream.dto.param.CommandParamDto;
import org.i9.slb.platform.anseko.downstream.dto.param.FileCommandParamDto;
import org.i9.slb.platform.anseko.downstream.dto.param.GroupCommandParamDto;
import org.i9.slb.platform.anseko.downstream.dto.param.ShellCommandParamDto;
import org.i9.slb.platform.anseko.hypervisors.AbstractSimulatorBuilder;
import org.i9.slb.platform.anseko.hypervisors.AbstractSimulatorOperate;
import org.i9.slb.platform.anseko.hypervisors.param.SimulatorDisk;
import org.i9.slb.platform.anseko.hypervisors.param.SimulatorInfo;
import org.i9.slb.platform.anseko.hypervisors.param.SimulatorNetwork;
import org.i9.slb.platform.anseko.hypervisors.param.SimulatorViewer;
import org.i9.slb.platform.anseko.provider.dto.InstanceDto;
import org.i9.slb.platform.anseko.provider.dto.SimulatorDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 模拟器操作服务类
 *
 * @author R12
 * @date 2018.08.31
 */
@Service("simulatorServiceImpl")
public class SimulatorServiceImpl implements SimulatorService {

    @Autowired
    private CoreserviceRemoteService coreserviceRemoteService;

    @Autowired
    private CommandExecuteRemoteService commandExecuteRemoteService;

    /**
     * 创建模拟器
     *
     * @param simulatorDto
     */
    @Override
    public SimulatorInfo createSimulator(SimulatorDto simulatorDto) {
        InstanceDto instanceDto = this.coreserviceRemoteService.remoteServiceGetInstanceDtoInfo(simulatorDto.getInstance());

        SimulatorInfo simulatorInfo = new SimulatorInfo(simulatorDto.getSimulatorName(), 4, 4096);
        AbstractSimulatorOperate simulatorOperate = SimulatorBuilderFactory.make(simulatorDto.getSimulatorName(), instanceDto.getVirtualEnum());

        List<CommandParamDto> commands = new ArrayList<CommandParamDto>();
        for (String commandLine : simulatorOperate.createDiskPath()) {
            ShellCommandParamDto shellCommandParamDto = ShellCommandParamDto.build(commandLine);
            commands.add(shellCommandParamDto);
        }

        SimulatorViewer simulatorViewer = new SimulatorViewer(simulatorDto.getVncport(), simulatorDto.getVncpassword());
        simulatorInfo.setSimulatorViewer(simulatorViewer);

        SimulatorDisk simulatorDisk = new SimulatorDisk(UUID.randomUUID().toString(), "/dev/disk1/" + simulatorInfo.getName());
        simulatorInfo.getSimulatorDisks().add(simulatorDisk);

        SimulatorNetwork simulatorNetwork = new SimulatorNetwork(
                UUID.randomUUID().toString(), "vnet-" + simulatorInfo.getUuid(), SimulatorUtils.randomMAC(), 10);
        simulatorInfo.getSimulatorNetworks().add(simulatorNetwork);

        FileCommandParamDto fileCommandParamDto = new FileCommandParamDto();
        fileCommandParamDto.setCommandId(UUID.randomUUID().toString());

        AbstractSimulatorBuilder simulatorBuilder =SimulatorBuilderFactory.make(simulatorInfo, instanceDto.getVirtualEnum());

        fileCommandParamDto.setFileContent(simulatorBuilder.makeDefineSimulatorFile());
        fileCommandParamDto.setFilePath("/tmp/" + simulatorInfo.getName() + ".xml");
        fileCommandParamDto.setCommandLine("virsh define " + fileCommandParamDto.getFilePath());
        commands.add(fileCommandParamDto);

        GroupCommandParamDto groupCommandParamDto = new GroupCommandParamDto();
        groupCommandParamDto.setGroupId(UUID.randomUUID().toString());
        groupCommandParamDto.setCommands(commands);
        // 执行远程调用服务
        this.coreserviceRemoteService.remoteServiceLaunchCommandDispatch(simulatorDto.getSimulatorName(), groupCommandParamDto);

        String instance = this.coreserviceRemoteService.remoteServiceGetInstanceRemoteAddress(simulatorDto.getInstance());
        this.commandExecuteRemoteService.multipleCommandExecute(instance, groupCommandParamDto);

        return simulatorInfo;
    }

    /**
     * 关闭模拟器
     *
     * @param simulatorDto
     */
    @Override
    public void shutdownSimulator(SimulatorDto simulatorDto) {
        InstanceDto instanceDto = this.coreserviceRemoteService.remoteServiceGetInstanceDtoInfo(simulatorDto.getInstance());
        AbstractSimulatorOperate simulatorOperate = SimulatorBuilderFactory.make(simulatorDto.getSimulatorName(), instanceDto.getVirtualEnum());
        String commandLine = simulatorOperate.shutdownSimulator();
        ShellCommandParamDto shellCommandParamDto = ShellCommandParamDto.build(commandLine);
        // 执行远程调用服务
        this.coreserviceRemoteService.remoteServiceLaunchCommandDispatch(simulatorDto.getId(), shellCommandParamDto);

        String instance = this.coreserviceRemoteService.remoteServiceGetInstanceRemoteAddress(simulatorDto.getInstance());
        this.commandExecuteRemoteService.shellCommandExecute(instance, shellCommandParamDto);
    }

    /**
     * 启动模拟器
     *
     * @param simulatorDto
     */
    @Override
    public void startSimulator(SimulatorDto simulatorDto) {
        InstanceDto instanceDto = this.coreserviceRemoteService.remoteServiceGetInstanceDtoInfo(simulatorDto.getInstance());
        AbstractSimulatorOperate simulatorOperate = SimulatorBuilderFactory.make(simulatorDto.getSimulatorName(), instanceDto.getVirtualEnum());
        String commandLine = simulatorOperate.startSimulator();
        ShellCommandParamDto shellCommandParamDto = ShellCommandParamDto.build(commandLine);
        // 执行远程调用服务
        this.coreserviceRemoteService.remoteServiceLaunchCommandDispatch(simulatorDto.getId(), shellCommandParamDto);

        String instance = this.coreserviceRemoteService.remoteServiceGetInstanceRemoteAddress(simulatorDto.getInstance());
        this.commandExecuteRemoteService.shellCommandExecute(instance, shellCommandParamDto);
    }

    /**
     * 重启模拟器
     *
     * @param simulatorDto
     */
    @Override
    public void rebootSimulator(SimulatorDto simulatorDto) {
        InstanceDto instanceDto = this.coreserviceRemoteService.remoteServiceGetInstanceDtoInfo(simulatorDto.getInstance());
        AbstractSimulatorOperate simulatorOperate = SimulatorBuilderFactory.make(simulatorDto.getSimulatorName(), instanceDto.getVirtualEnum());
        List<ShellCommandParamDto> shellCommandParamDtos = new ArrayList<ShellCommandParamDto>();

        for (String commandLine : simulatorOperate.rebootSimulator()) {
            ShellCommandParamDto shellCommandParamDto = ShellCommandParamDto.build(commandLine);
            shellCommandParamDtos.add(shellCommandParamDto);
        }

        // 执行远程调用服务
        this.coreserviceRemoteService.remoteServiceLaunchCommandDispatch(simulatorDto.getId(), shellCommandParamDtos);

        String instance = this.coreserviceRemoteService.remoteServiceGetInstanceRemoteAddress(simulatorDto.getInstance());
        this.commandExecuteRemoteService.shellCommandExecuteBatch(instance, shellCommandParamDtos);
    }

    /**
     * 销毁模拟器
     *
     * @param simulatorDto
     */
    @Override
    public void destroySimulator(SimulatorDto simulatorDto) {
        InstanceDto instanceDto = this.coreserviceRemoteService.remoteServiceGetInstanceDtoInfo(simulatorDto.getInstance());
        AbstractSimulatorOperate simulatorOperate = SimulatorBuilderFactory.make(simulatorDto.getSimulatorName(), instanceDto.getVirtualEnum());
        List<ShellCommandParamDto> shellCommandParamDtos = new ArrayList<ShellCommandParamDto>();

        for (String commandLine : simulatorOperate.destroySimulator()) {
            ShellCommandParamDto shellCommandParamDto = ShellCommandParamDto.build(commandLine);
            shellCommandParamDtos.add(shellCommandParamDto);
        }

        // 执行远程调用服务
        this.coreserviceRemoteService.remoteServiceLaunchCommandDispatch(simulatorDto.getId(), shellCommandParamDtos);

        String instance = this.coreserviceRemoteService.remoteServiceGetInstanceRemoteAddress(simulatorDto.getInstance());
        this.commandExecuteRemoteService.shellCommandExecuteBatch(instance, shellCommandParamDtos);
    }
}
